package modelos;

import java.io.FileNotFoundException;
import java.io.IOException;

import edu.bonn.cs.iv.bonnmotion.MobileNode;
import edu.bonn.cs.iv.bonnmotion.Position;
import edu.bonn.cs.iv.bonnmotion.RandomSpeedBase;
import edu.bonn.cs.iv.bonnmotion.Scenario;

public class ModeloCircular extends RandomSpeedBase {
	private static final String MODEL_NAME = "ModeloCircular";

	private double raioMax = 50.0;
	private double raioMin = 1.0;
	
	public ModeloCircular(int nodes, double x, double y, double duration, double ignore, long randomSeed, double minspeed, double maxspeed, double maxpause) {
		super(nodes, x, y, duration, ignore, randomSeed, minspeed, maxspeed, maxpause);
		generate();
	}

	public ModeloCircular( String[] args ) {
		go(args);
	}

	public void go( String[] args ) {
		super.go(args);
		generate();
	}

	public void generate() {
		preGeneration();

		System.out.println("node count " + this.nodeCount());
		
		for (int i = 0; i < this.nodeCount(); i++) {
			node[i] = new MobileNode();

			double raio = (raioMax - raioMin) * randomNextDouble() + raioMin;;
			double radianos = 0.0; 
			double delta = 0.0;
			double speed;
			Position centro = randomNextPosition();
			
			for (double t = 0.0; t < this.duration; t += (delta * raio) / speed) {
				speed = (maxspeed - minspeed) * randomNextDouble() + minspeed;
				delta = (rand.nextInt(359) + 1) * 2 * Math.PI / 360;
								
				radianos += delta;
				Position pos = getPosition(radianos, raio, centro);
				
				if (! (node[i].add(t, pos)))
					throw new RuntimeException(MODEL_NAME + ".go: error while adding waypoint");
			} 
		}

		postGeneration();
	}

	/**
	 * Calcula a proxima posicao
	 * @param radianos o angulo da direcao
	 * @param raio tamanho do raio
	 * @param centro posicao do centro da circunferencia
	 * @return a nova posicao
	 */
	private Position getPosition(double radianos, double raio, Position centro) {
		double x_ = 0.0, y_ = 0.0;
		x_ = raio * Math.cos(radianos) + centro.x;
		y_ = raio * Math.sin(radianos) + centro.y;
		
		// se sai dos limites, ele anda na borda
		x_ = (x_ <  0.0) ? 0.0 : x_;
		x_ = (x_ >  x) ?  x : x_;
		
		y_ = (y_ <  0.0) ? 0.0 : y_;
		y_ = (y_ >  y) ?  y : y_;
		
		return new Position(x_, y_);
	}

	public void write( String _name ) throws FileNotFoundException, IOException {
		String[] p = new String[2];
		p[0] = "raioMin=" + raioMin;
		p[1] = "raioMax=" + raioMax;
		super.write(_name, p);
	}

	protected boolean parseArg(String key, String val) {
		if (key.equals("raioMax")) {
			raioMax = Double.parseDouble(val);
		} else if (key.equals("raioMin")) {
			raioMin = Double.parseDouble(val);
		} else return super.parseArg(key, val);
		
		return true;
	}

	protected boolean parseArg(char key, String val) {
		switch (key) {
		case 'M':
			raioMax = Double.parseDouble(val);
			return true;
		case 'm':
			raioMin = Double.parseDouble(val);
			return true;
		default:
			return super.parseArg(key, val);
		}
	}
	public static void printHelp() {
		Scenario.printHelp();
		System.out.println( MODEL_NAME + ":" );
		System.out.println("\t-m <tamanho do raio minimo>");
		System.out.println("\t-M <tamanho do raio maximo>");
	}

}
